package com.ruyuan2020.im.juc;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerConsumerExample {
    // 共享的缓冲区
    private final Queue<Integer> buffer = new LinkedList<>();
    // 缓冲区最大容量
    private static final int MAX_SIZE = 5;
    // 锁对象
    private final Lock lock = new ReentrantLock();
    // 生产者条件
    private final Condition producerCondition = lock.newCondition();
    // 消费者条件
    private final Condition consumerCondition = lock.newCondition();

    // 生产者方法
    public void produce() throws InterruptedException {
        lock.lock();
        try {
            while (buffer.size() == MAX_SIZE) {
                // 缓冲区满，生产者等待
                producerCondition.await();
            }
            // 生产一个数据
            int data = (int) (Math.random() * 100);
            buffer.offer(data);
            System.out.println("Produced: " + data);
            // 通知消费者
            consumerCondition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    // 消费者方法
    public void consume() throws InterruptedException {
        lock.lock();
        try {
            while (buffer.isEmpty()) {
                // 缓冲区空，消费者等待
                consumerCondition.await();
            }
            // 消费一个数据
            int data = buffer.poll();
            System.out.println("Consumed: " + data);
            // 通知生产者
            producerCondition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    // 客户端调用示例
    public static void main(String[] args) {
        ProducerConsumerExample pc = new ProducerConsumerExample();

        // 创建生产者线程
        Thread producerThread = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    pc.produce();
                    Thread.sleep(100); // 模拟生产耗时
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 创建消费者线程
        Thread consumerThread = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    pc.consume();
                    Thread.sleep(150); // 模拟消费耗时
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 启动线程
        producerThread.start();
        consumerThread.start();
    }
}

